package org.jeecg.modules.monitoring.j_monitoring.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xkcoding.http.util.StringUtil;
import org.jeecg.common.api.vo.Result;
import org.jeecg.config.vo.HttpResult;
import org.jeecg.modules.monitoring.j_monitoring.constantConfig.MonitorStatusEnum;
import org.jeecg.modules.monitoring.j_monitoring.entity.*;
import org.jeecg.modules.monitoring.j_monitoring.entity.fdnEntity.*;
import org.jeecg.modules.monitoring.j_monitoring.gatewayData.ComputeResources;
import org.jeecg.modules.monitoring.j_monitoring.gatewayData.NetworkResources;
import org.jeecg.modules.monitoring.j_monitoring.gatewayData.StorageResources;
import org.jeecg.modules.monitoring.j_monitoring.gatewayData.Virtual;
import org.jeecg.modules.monitoring.j_monitoring.mapper.NetworkInterfaceLogMapper;
import org.jeecg.modules.monitoring.j_monitoring.mapper.RealVirtualHostMapper;
import org.jeecg.modules.monitoring.j_monitoring.service.IMGlVirtualMachineService;
import org.springframework.core.env.Environment;
import org.jeecg.config.sign.util.NoSslHttpUtils;
import org.jeecg.modules.monitoring.j_monitoring.mapper.GatewaySystemFdnMapper;
import org.jeecg.modules.monitoring.j_monitoring.service.IGatewaySystemFdnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 网关系统FND服务
 * @Author: xiaoyq
 * @Date:   2023-02-11
 * @Version: V1.0
 */
@Service
@EnableScheduling
public class GatewaySystemFdnServiceImpl extends ServiceImpl<GatewaySystemFdnMapper, GatewaySystemFdn> implements IGatewaySystemFdnService {

    @Autowired
    private Environment env;
    @Resource
    MGlStorageResourcesServiceImpl storageService;
    @Resource
    StorageResources storageResources;
    @Resource
    NetworkResources networkResources;

    @Resource
    ComputeResources computeResources;

    @Resource
    MGlNetworkResourceServiceImpl networkResourceService;

    @Resource
    IMGlVirtualMachineService virtualMachineService;

    @Resource
    MGlComputingResourceServiceImpl physicalServerService;

    @Resource
    private NetworkInterfaceLogMapper logMapper;

    @Resource
    private MGlUpsServiceImpl upsService;
    @Resource
    private MGlPrecisionAirConditionerServiceImpl airConditionerService;

    @Resource
    private GatewayWarningServiceImpl gatewayWarningService;

    @Resource
    private Virtual virtual;

    @Resource
    private RealVirtualHostMapper virtualHostMapper;

    /**
     * 虚拟化集群
     */
    @Resource
    private MGlVirtualizationClusterServiceImpl virtualizationClusterService;
    private String allList = "/ng/integration/devicesList"; //全部设备列表

    private String deviceMonitorsSummary = "/ng/integration/deviceMonitorsSummary"; //获取所有监控点

    private String deviceMonitors = "/ng/integration/deviceMonitors"; //获取设备监控数据

    /**
     * 同步Fdn
     */
    public void syncFdn(){

        String url = env.getProperty("gatewaySystem.url");

        String header = env.getProperty("gatewaySystem.header");

        try {
            HttpResult res = NoSslHttpUtils.noSslGet(url+allList,header);

            List<Devices> list = JSONArray.parseArray(res.getBody(), Devices.class);

            baseMapper.removeAll();

            for (Devices devices : list){
                GatewaySystemFdn systemFdn = new GatewaySystemFdn();
                systemFdn.setFdn(devices.getFdn());
                systemFdn.setIp(devices.getIp());
                systemFdn.setType("1");

                baseMapper.insert(systemFdn);

            }

            List<RealVirtualHost> hostList = virtualHostMapper.selectAll();
            for (RealVirtualHost host : hostList){
                GatewaySystemFdn systemFdn = new GatewaySystemFdn();
                systemFdn.setFdn(host.getFdn());
                systemFdn.setIp(host.getIp());
                systemFdn.setType("2");
                baseMapper.insert(systemFdn);
            }


        }catch (Exception e){
            e.printStackTrace();
            System.out.println(e);
        }

    }

    /**
     * 是否可以添加
     * @param fdnList
     * @param systemFdn
     * @return
     */
    private Boolean canInsert(List<GatewaySystemFdn> fdnList,GatewaySystemFdn systemFdn){

        if (StringUtil.isEmpty(systemFdn.getIp()) || systemFdn.getIp().length()==0){
            return false;
        }
        for (GatewaySystemFdn fdn : fdnList){

            if (fdn.getIp().equals(systemFdn.getIp()) && fdn.getFdn().equals(systemFdn.getFdn())){
                return false;
            }

        }
        return true;
    }

    /**
     * 根据type，id获得网关数据
     * @param type 1.网络资源 2.计算资源 3.虚拟机 4.存储资源
     * @param id  id
     * @return
     */
    public Result getGatewayData(int type,String id){

        String fdn = this.gateFdnByTypeAndId(type,id);
        if (StringUtil.isEmpty(fdn)){
            return Result.error("未找到设备fdn参数");
        }

        switch (type){
            case 1:
                return Result.ok(networkResources.getData(fdn));
            case 2:
                MGlComputingResource computingResource = physicalServerService.selectById(id);
                return Result.ok(computeResources.getData(fdn,computingResource.getMonitorWay()));
            case 3:

                break;
            case 4:
                return Result.ok(storageResources.getData(fdn));
            default:
                return Result.error("参数错误");
        }

        return Result.error("参数错误");
    }

    /**
     * 根据type，id获得网关数据
     * @param type 类型
     * @param id  id
     * @return
     */
    public String gateFdnByTypeAndId(int type,String id){
        String ip = "";
        String way = "1";
        switch (type){
            case 1:
                ip = networkResourceService.getIp(id);
                break;
            case 2:
                //计算资源做处理
                MGlComputingResource computingResource = physicalServerService.selectById(id);
                ip = computingResource.getDeviceIp();
                way = "间接监控".equals(computingResource.getMonitorWay()) ?"2":"1";
                break;
            case 3:
                ip = virtualMachineService.getIp(id);
                break;
            case 4:
                ip = storageService.getIp(id);
                break;
            case 5:
                ip = virtualizationClusterService.getIp(id);
                break;
            default:
                return "";
        }
        String fdn = this.getFdnByIp(ip,way);

        if (StringUtil.isEmpty(fdn)){
            return "";
        }

        return fdn;
    }

    public String getFdnByIp(String ip,String type){
        QueryWrapper<GatewaySystemFdn> queryWrapper = new QueryWrapper<GatewaySystemFdn>();
        queryWrapper.eq("ip",ip).eq("type",type);
        List<GatewaySystemFdn> fdnList = baseMapper.selectList(queryWrapper);

        if (fdnList.size()==0){
            return "";
        }

        return fdnList.get(0).getFdn();
    }

    /**
     * 根据type，id获得网关数据
     * @param type 类型
     * @param id  id
     * @return
     */
    public Result showIpInterface(int type,String id){

        String fdn = this.gateFdnByTypeAndId(type,id);
        if (StringUtil.isEmpty(fdn)){
            return Result.error("未找到设备fdn参数");
        }
        return Result.ok(networkResources.showIpInterface(fdn));
    }

    /**
     * 根据id获得IP接口列表
     * @param id  id
     * @return
     */
    public Result getIpInterfaceList(String id){

        String fdn = this.gateFdnByTypeAndId(1,id);
        if (StringUtil.isEmpty(fdn)){
            return Result.error("未找到设备fdn参数");
        }
        return Result.ok(networkResources.getIpInterfaceList(fdn));
    }

    /**
     * 根据id名称获得网络设备信息
     * @param id  设备id
     * @param name  设备名称
     * @return
     */
    public Result NetWorkFlowList(String id,String name){

        String fdn = this.gateFdnByTypeAndId(1,id);
        if (StringUtil.isEmpty(fdn)){
            return Result.error("未找到设备fdn参数");
        }
        return Result.ok(logMapper.selectByFdnAndName(fdn,name));
    }

    /**
     * 添加设备监控
     * @param type  类型
     * @param id  id
     * @return
     */
    public Result insertMonitor(int type,String id){

        String fdn = this.gateFdnByTypeAndId(type,id);
        if (StringUtil.isEmpty(fdn) && type < 10 && type != 3){
            return Result.error("请在网管系统中添加设备再进行操作");
        }
        switch (type){
            case 1:
                MGlNetworkResource resource = networkResourceService.getById(id);
                resource.setWhetherToMonitor("1");
                return Result.ok(networkResourceService.updateById(resource));

            case 2:
                MGlComputingResource computingResource = physicalServerService.getById(id);
                computingResource.setWhetherToMonitor("1");
                return Result.ok(physicalServerService.updateById(computingResource));
            case 3:
                MGlVirtualMachine virtualMachine = virtualMachineService.getById(id);
                virtualMachine.setWhetherToMonitor("1");
                return Result.ok(virtualMachineService.updateById(virtualMachine));
            case 4:
                MGlStorageResources storageResources1 = storageService.getById(id);
                storageResources1.setWhetherToMonitor("1");
                storageService.updateById(storageResources1);
                //添加监控重新跑脚本
                this.SyncStorageItem();
                return Result.ok();
            case 45:
                MGlVirtualizationCluster virtualizationCluster = virtualizationClusterService.getById(id);
                virtualizationCluster.setWhetherToMonitor("1");
                return Result.ok(virtualizationClusterService.updateById(virtualizationCluster));
            case 50:
                MGlUps ups = upsService.getById(id);
                ups.setWhetherToMonitor("1");
                return Result.ok(upsService.updateById(ups));
            case 60:
                MGlPrecisionAirConditioner air = airConditionerService.getById(id);
                air.setWhetherToMonitor("1");
                return Result.ok(airConditionerService.updateById(air));
            default:
                return Result.error("参数错误");
        }
    }


    public String getItemName(VirtulResultChild resultChild){

        try {

            List<VirtuChildResult> requestResult = virtual.getChildMOs(resultChild.getFdn());
            if (requestResult.size()==0){
                resultChild.getLabel();
            }

            for (VirtuChildResult r : requestResult){
                return r.getChildren().get(0).getLabel();
            }


        }catch (Exception e){
            e.printStackTrace();
        }
        return resultChild.getLabel();
    }



    public void syncIPInterface(){

        //已监测的保留7天 未观测的全保留3小时
        //删除3小时前的数据
        logMapper.deleteSyncData();
        logMapper.deleteKeyData();

        String url = env.getProperty("gatewaySystem.url");

        String header = env.getProperty("gatewaySystem.header");

        try {

            HttpResult res = NoSslHttpUtils.noSslGet(url+allList,header);

            List<Devices> list = JSONArray.parseArray(res.getBody(), Devices.class);

            for (Devices devices : list){

                //华为交换机 网络设备记录
                if ( devices.getFdn().indexOf("HuaweiSwitch")!= -1){
                    networkResources.syncIpInterface(devices.getFdn());
                }
            }

        }catch (Exception e){
            e.printStackTrace();
            System.out.println(e);
        }


    }


    /**
     * 异常状态 1正常 2有预警 3ping不通
     * @param ipList
     * @return
     */
    public Map<String,Object> getPingMonitor(List<String> ipList){


        Map<String,Object> res = new HashMap<>();

        if (ipList.size()==0){
            return res;
        }

        //测试环境默认全部ping通
        if (!"prod".equals(env.getProperty("spring.profiles.active"))) {
           for (String ip : ipList){
               res.put(ip, MonitorStatusEnum.online.getKey() );
           }
           return res;
        }else{
            for (String ip : ipList){
                res.put(ip, MonitorStatusEnum.offline.getKey() );
            }
        }


        try {

            QueryWrapper<GatewaySystemFdn> queryWrapper = new QueryWrapper<GatewaySystemFdn>();
            queryWrapper.in("ip",ipList);
            List<GatewaySystemFdn> gatewayFdnList = baseMapper.selectList(queryWrapper);
            if (gatewayFdnList.size()==0){
                return res;
            }
            List<String> fdnList = gatewayFdnList.stream().map(e -> e.getFdn()).collect(Collectors.toList());
            Map<String,String> fdnIp =  gatewayFdnList.stream().collect(Collectors.toMap(GatewaySystemFdn::getFdn, GatewaySystemFdn::getIp, (key1, key2) -> key2));
            String result = fdnList.stream().map(String::valueOf).collect(Collectors.joining(","));

            String url = env.getProperty("gatewaySystem.url");
            String header = env.getProperty("gatewaySystem.header");
            String deviceMonitors = "/ng/integration/deviceMonitors";


            String queryUrl = url + deviceMonitors + "?types=PingMonitor&device_fdns=" + result;

            HttpResult httpResult = NoSslHttpUtils.noSslGet(queryUrl, header);
            String json = httpResult.getBody();
            List<DevicesMonitors> monitorsList = JSONArray.parseArray(json, DevicesMonitors.class);
            List<GatewayWarning> warningList = gatewayWarningService.getWarningByFdnList(fdnList);

            for (DevicesMonitors monitors : monitorsList){
                int resultNum = 1;
                if (monitors.getMonitors().size()==0){
                    continue;
                }
                for (DevicesData devicesData : monitors.getMonitors().get(0).getCounters()){
                    if ("Status".equals(devicesData.getName()) && "1".equals(devicesData.getValue())){
                        //能ping通
                        resultNum = this.getIsWarning(warningList,monitors.getFdn())? new Integer(MonitorStatusEnum.warning.getKey())  :new Integer(MonitorStatusEnum.online.getKey());
                        res.put(fdnIp.get(monitors.getFdn()),resultNum);
                    }

                    if ("Response Time".equals(devicesData.getName())) {
                        //能ping通
                        res.put("time"+fdnIp.get(monitors.getFdn()),devicesData.getValue()+ devicesData.getUnit());
                    }


                }
            }

            return res;

        }catch (Exception e){
            return res;
        }


    }

    public boolean getIsWarning(List<GatewayWarning> warningList,String fdn){
        for (GatewayWarning warning : warningList){
            if (warning.getFdn().contains(fdn)){
                return true;
            }
        }


        return false;
    }


    //同步虚拟机
    public void syncVirtually(){
        //todo 先写死三台虚拟机机器 后改为动态配置
        List<String> ipList = new ArrayList<String>(){
            {
//                add("10.57.2.60");
//                add("10.57.132.80");
                add("10.57.3.100");
            }
        };



        for (String ip : ipList){
            String fdn = getFdnByIp(ip,"1");
            if (StringUtil.isEmpty(fdn)){
                continue;
            }

            syncCluster(fdn,ip);

        }



    }

    /**
     * 递归获取数据
     * @param fdn
     * @param ip
     */
    public void syncCluster(String fdn,String ip){

        List<VirtuChildResult> requestResult = virtual.getChildMOs(fdn);
        if (requestResult.size()==0){
            return;
        }


        for (VirtuChildResult result : requestResult){

            if (result.getLabel().contains("数据中心")){

                for (VirtulResultChild child : result.getChildren()){
                    //监控虚拟机集群数据
                    RealVirtualCluster cluster = virtual.saveOrUpdateCluster(child,ip);

                    List<VirtuChildResult> childResultList = virtual.getChildMOs(child.getFdn());
                    // 虚拟主机  虚拟机层
                    for (VirtuChildResult r : childResultList){
                        if ("主机".equals(r.getLabel())){

                            for (VirtulResultChild hostChild : r.getChildren()){
                                virtual.saveOrUpdateHost(r,cluster,hostChild);
                            }

                        }

                        if ("虚拟机组".equals(r.getLabel())){

                            for (VirtulResultChild hostChild : r.getChildren()){
                                //虚拟机名称再循环调接口获取
                                String itemName = this.getItemName(hostChild);

                                virtual.saveOrUpdateItem(hostChild,itemName,cluster.getId());

                            }

                        }


                    }


                }


            }

        }

    }

    /**
     * 根据名称和ip查询虚拟群集信息
     * @param name
     * @param ip
     * @return
     */
    public Result virtualClusterInfo(String name,String ip){
        Map<String,Object> map = new HashMap<>();

        RealVirtualCluster cluster = virtual.getRealVirtualClusterByIpAndName(ip,name);
        if (cluster!=null){
            map.put("cluster",cluster);
            map.put("hostList",virtual.getHostsById(cluster.getId()));
        }

        return Result.OK(map);
    }

    /**
     * 根据名称查询机房信息
     * @param name
     * @return
     */
    public Result machineInfo(String name){

        return Result.OK(virtual.getItem(name));
    }

    public void SyncStorageItem(){
        //取所有已监控的数据
        List<MGlStorageResources> storageResourcesList = storageService.getMonitorList();
        for (MGlStorageResources storage : storageResourcesList){

            String fdn = this.getFdnByIp(storage.getDeviceIp(),"1");
            if (StringUtil.isEmpty(fdn)){
                continue;
            }
            String type = storageResources.getType(fdn);
            if (StringUtil.isEmpty(type)){
                continue;
            }
            BigDecimal used = new BigDecimal(0);
            //取数据
            switch (type){
                case "huawei":
                    used = storageResources.syncHuaweiItem(fdn,storage.getDeviceIp());
                    break;
                case "sugon":
                    used = storageResources.syncSugonItem(fdn,storage.getDeviceIp());
                    break;
                case "dell":
                    used = storageResources.syncDellUsed(fdn);
                    break;
                case "netApp":
                    used = storageResources.syncNetAppUsed(fdn);
                    break;
            }


            storage.setUsedCapacity(used);
            storageService.updateById(storage);
        }
    }

}
